package cate.game.role.mail;

import cate.common.game.GameCollection;
import cate.common.table.d.GDMail;
import cate.common.util.GameResult;
import cate.game.event.mail.MailGetRewardEvent;
import cate.game.mail.po.MailBox;
import cate.game.role.mail.msg.MailAddResp;
import cate.game.role.mail.msg.MailDeleteResp;
import cate.game.res.MixRes;
import cate.game.role.Role;
import cate.game.role.RolePart;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Document(collection = GameCollection.NAME_ROLE_MAIL)
public class RoleMail extends RolePart {
    @NoteField(value = "上次查收邮件时间")
    @JsonIgnore
    public long lastCheckTime;

    @NoteField(value = "邮件列表")
    public List<Mail> list;

    @NoteField(value = "GM邮件处理")
    public RoleGmMail gm;

    @NoteField("0920bug处理")
    public boolean bugFix0920;

    public RoleMail() {

    }

    public RoleMail(Role role) {
        super(role);
        list = new ArrayList<>();
    }

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if(gm == null) {
            gm = new RoleGmMail();
        }
        gm.initialize(this);
    }

    @Override
    public void onEnter(){
        checkMails();
        if (!bugFix0920) {
            bugFix0920 = true;
            list.removeIf(mail -> mail != null && StringUtils.isNotBlank(mail.getTitle()) && StringUtils.equals(mail.getTitle(), "获得物品"));
        }
        gm.onEnter();
    }

    /**
     * 添加邮件
     */
    public synchronized void add(Mail mail) {
        // 如果邮件满了 尝试删除的邮件 并领取奖励（为了防止出现循环删除添加，现在不采取领取奖励的策略，直接删除）
        if (list.size() >= GDMail.MAX_NUM) {
            //已读没有附件
            int i = getReadNoRewardMailIndex();
            if (i == -1) {
                //没有附件
                i = getNoReadNoRewardMailIndex();
            }
            if (i == -1) {
                //已读
                i = getReadRewardMailIndex();
            }
            if (i == -1) {
                i = 0;
            }
            Mail deleteMail = list.get(i);
            // 为了防止出现循环删除添加，现在不采取领取奖励的策略，直接删除
            list.remove(i);
            // 通知被删除的邮件
            MailDeleteResp resp = new MailDeleteResp();
            resp.deletedIdHexList = new ArrayList<>();
            resp.deletedIdHexList.add(deleteMail.uid);
            role.sendNow(resp);
        }
        list.add(mail);
        role.sendNow(new MailAddResp(mail));
    }

    /**
     * @return 邮件索引
     */
    @JsonIgnore
    private int getReadNoRewardMailIndex() {
        // 首先尝试寻找一封没有附件的邮件
        for (int i = 0; i < this.list.size(); i++) {
            Mail mail = list.get(i);
            if ((mail.reward == null || mail.reward.isEmpty() || mail.got) && mail.read) {
                return i;
            }
        }
        return -1;
    }

    /**
     * @return 邮件索引
     */
    @JsonIgnore
    private int getNoReadNoRewardMailIndex() {
        // 首先尝试寻找一封没有附件的邮件
        for (int i = 0; i < this.list.size(); i++) {
            Mail mail = list.get(i);
            if (mail.reward == null || mail.reward.isEmpty() || mail.got) {
                return i;
            }
        }
        return -1;
    }

    /**
     * @return 邮件索引
     */
    @JsonIgnore
    private int getReadRewardMailIndex() {
        // 首先尝试寻找一封没有附件的邮件
        for (int i = 0; i < this.list.size(); i++) {
            Mail mail = list.get(i);
            if (mail.read) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 查收邮件
     */
    public void checkMails() {
        long now = System.currentTimeMillis();
        lastCheckTime = now;
        MailBox box = role.getGame().mail.getBox(this.role.getUid(), false);
        if (box != null) {
            box.addToRole(this.role);
        }
        synchronized (this){
            // 删除玩家身上超过28天的邮件
            list.removeIf(mail -> mail.createTime + GDMail.MAX_TIME < now);
        }
    }

    /**
     * 执行邮件操作
     */
    public synchronized GameResult<List<Mail>> oper(List<String> readList, List<String> gotList) {
        GameResult<List<Mail>> r = new GameResult<>();
        List<Mail> rwdGotList = new ArrayList<>();
        List<Mail> updates = new ArrayList<>();
        Iterator<Mail> iterator = list.iterator();
        MixRes rewardGotTotal = new MixRes(); // 总共领取的奖励
        GameResult<Void> operRes = null;
        while (iterator.hasNext()) {
            Mail old = iterator.next();
            role.log.setOperation(old.operation, old.operationSub);
            boolean updated = false;
            if (readList != null && readList.contains(old.uid)) {
                old.read = true;
                updated = true;
            }
            if (gotList != null && gotList.contains(old.uid) && !old.got) {
                operRes = old.reward.add(role);
                if (operRes.ok()) {
                    old.got = true;
                    old.read = true;
                    rewardGotTotal.addList(old.reward);
                    rwdGotList.add(old);
                    updated = true;
                } else {
                    break;
                }
            }
            if (updated) {
                updates.add(old);
            }
        }
        role.log.clearOperation();
        if (rewardGotTotal.items != null && !rewardGotTotal.items.isEmpty()) {
            role.getGame().notice.dialogReward(role, rewardGotTotal);
            publishEvent(role, new MailGetRewardEvent(role, rwdGotList));
        }
        r.data = updates;
        if (!updates.isEmpty()) {
            return r.success();
        } else {
            return operRes != null ? r.fail(operRes) : r.fail("没有可以操作的邮件");
        }
    }

    /**
     * 删除邮件
     */
    public synchronized EcResult<List<String>> delete(List<String> uidList, boolean deleteRead, boolean deleteGot) {
        EcResult<List<String>> r = new EcResult<>();
        List<String> deletedIdHexList = new ArrayList<>();
        Iterator<Mail> iterator = list.iterator();
        while (iterator.hasNext()) {
            Mail old = iterator.next();
            boolean needDelete = false;
            if (deleteRead && old.read) {
                if (old.reward == null || old.reward.isEmpty() || old.got) {
                    needDelete = true;
                }
            } else if (deleteGot && old.got) {
                needDelete = true;
            } else if (uidList != null && uidList.contains(old.uid)) {
                needDelete = true;
            }
            if (needDelete) {
                deletedIdHexList.add(old.uid);
                iterator.remove();
            }
        }
        r.data = deletedIdHexList;
        return r.success();
    }

    /**
     * 邮件
     */
    public void clearAll() {
        list.clear();
    }
}
